#include "../inc/stdio.h"
#include "../pic/pic.h"
#include "../trap/trap.h"
#include "../driver/intr.h"
#include "../driver/clock.h"
#include "../driver/console.h"
#include "../libs/string.h"
#include "../debug/kdebug.h"
// #include "../mm/pmm.h"
// #include "../gdt/gdt.h"
void kernMain(void) __attribute__((noreturn));
//用户态内核态切换
static void lab1_switch_test(void);
//打印调用栈
void grade_backtrace(void);
void kernMain(void){
    extern char edata[], end[];
    memset(edata, 0, end - edata);
    // 初始化控制台(控制显卡交互)
    cons_init();                // init the console
    printf("this is in c project hello word!\n");
    const char *message = "(THU.CST) os is loading ...";
    printf("test test %s\n\n test %d\n", message,100);
    // print_kerninfo();
    // grade_backtrace();
    // pmm_init();
    // gdt_init();
    // pic_init();
    // idt_init();
    // clock_init();
    // intr_enable();
    // lab1_switch_test();
    while (1);
}

static void lab1_print_cur_status(void) {
    static int round = 0;
    uint16_t reg1, reg2, reg3, reg4;
    asm volatile (
            "mov %%cs, %0;"
            "mov %%ds, %1;"
            "mov %%es, %2;"
            "mov %%ss, %3;"
            : "=m"(reg1), "=m"(reg2), "=m"(reg3), "=m"(reg4));
    printf("%d: @ring %d\n", round, reg1 & 3);
    printf("%d:  cs = %x\n", round, reg1);
    printf("%d:  ds = %x\n", round, reg2);
    printf("%d:  es = %x\n", round, reg3);
    printf("%d:  ss = %x\n", round, reg4);
    round ++;
}

void __attribute__((noinline)) grade_backtrace2(int arg0, int arg1, int arg2, int arg3) {
    mon_backtrace(0, NULL, NULL);
}

void __attribute__((noinline)) grade_backtrace1(int arg0, int arg1) {
    grade_backtrace2(arg0, (int)&arg0, arg1, (int)&arg1);
}

void __attribute__((noinline)) grade_backtrace0(int arg0, int arg1, int arg2) {
    grade_backtrace1(arg0, arg2);
}

void grade_backtrace(void) {
    grade_backtrace0(0, (int)kernMain, 0xffff0000);
}

static void lab1_switch_to_user(void) {
    //LAB1 CHALLENGE 1 : TODO
	asm volatile (
	    "sub $0x8, %%esp \n"
	    "int %0 \n"
	    "movl %%ebp, %%esp"
	    : 
	    : "i"(T_SWITCH_TOU)
	);
}
static void lab1_switch_to_kernel(void) {
    //LAB1 CHALLENGE 1 :  TODO
	asm volatile (
	    "int %0 \n"
	    "movl %%ebp, %%esp \n"
	    : 
	    : "i"(T_SWITCH_TOK)
	);
}


static void lab1_switch_test(void) {
    lab1_print_cur_status();
    printf("+++ switch to  user  mode +++\n");
    lab1_switch_to_user();
    lab1_print_cur_status();
    printf("+++ switch to kernel mode +++\n");
    lab1_switch_to_kernel();
    lab1_print_cur_status();
}
